local prefs = {}

local function MakeFx(data) -- 不需要网络功能
    table.insert(prefs, Prefab(
        data.name,
        function()
            local inst = CreateEntity()

            inst.entity:AddTransform()
            inst.entity:AddNetwork()

            -- Dedicated server does not need to spawn the local fx
            if not TheNet:IsDedicated() then
                -- Delay one frame so that we are positioned properly before starting the effect
                -- or in case we are about to be removed
                inst:DoTaskInTime(0, function(proxy)
                    local inst2 = CreateEntity()

                    --[[Non-networked entity]]

                    inst2.entity:AddTransform()
                    inst2.entity:AddAnimState()
                    inst2.entity:SetCanSleep(false)
                    inst2.persists = false

                    inst2:AddTag("FX")

                    local parent = proxy.entity:GetParent()
                    if parent ~= nil then
                        inst2.entity:SetParent(parent.entity)
                    end
                    inst2.Transform:SetFromProxy(proxy.GUID)

                    if data.fn_anim ~= nil then
                        data.fn_anim(inst2)
                    end

                    if data.fn_remove ~= nil then
                        data.fn_remove(inst2)
                    else
                        inst2:ListenForEvent("animover", inst2.Remove)
                    end
                end)
            end

            inst:AddTag("FX")

            if data.fn_common ~= nil then
                data.fn_common(inst)
            end

            inst.entity:SetPristine()
            if not TheWorld.ismastersim then return inst end

            inst.persists = false
            inst:DoTaskInTime(1, inst.Remove)

            return inst
        end,
        data.assets,
        nil
    ))
end
local function MakeFx2(data) -- 需要网络功能
    table.insert(prefs, Prefab(
        data.name,
        function()
            local inst = CreateEntity()

            inst.entity:AddTransform()
            inst.entity:AddAnimState()
            inst.entity:AddNetwork()

            inst:AddTag("FX")

            if data.fn_common ~= nil then
                data.fn_common(inst)
            end

            inst.entity:SetPristine()
            if not TheWorld.ismastersim then return inst end

            inst.persists = false

            if data.fn_server ~= nil then
                data.fn_server(inst)
            end

            return inst
        end,
        data.assets,
        nil
    ))
end

------

local function OnRemove_followfx(inst)
    for i, v in ipairs(inst.fx) do
        v:Remove()
    end
end
local function CreateNonNetInst(v)
    local inst = CreateEntity()

    --[[Non-networked entity]]
    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddFollower()

    inst:AddTag("FX")

    inst.persists = false

    inst:AddComponent("highlightchild") -- 这个组件是为了同步主体的高亮，达到一致性

    v.fn_anim(inst, v)

    return inst
end
local function SpawnFollowFxForOwner(inst, owner, fxdd)
    inst.fx = {}
    local frame
    for _, v in ipairs(fxdd) do
        local fx = CreateNonNetInst(v)
        if v.randomanim then
            frame = frame or math.random(fx.AnimState:GetCurrentAnimationNumFrames()) - 1
        end
        fx.entity:SetParent(owner.entity)
        fx.Follower:FollowSymbol(owner.GUID, v.symbol, v.x, v.y, v.z, true, nil, v.idx, v.idx2)
        if frame ~= nil then
            fx.AnimState:SetFrame(frame)
        end
        fx.components.highlightchild:SetOwner(owner)
        table.insert(inst.fx, fx)
    end
    inst.OnRemoveEntity = OnRemove_followfx
end
local function MakeFxFollow(data) -- 绑定式特效
    local function OnEntityReplicated(inst)
        local owner = inst.entity:GetParent()
        if owner ~= nil then
            SpawnFollowFxForOwner(inst, owner, data.fx)
        end
    end
    local function AttachToOwner(inst, owner)
        inst.entity:SetParent(owner.entity)
        -- Dedicated server does not need to spawn the local fx
        if not TheNet:IsDedicated() then
            SpawnFollowFxForOwner(inst, owner, data.fx)
        end
    end

    table.insert(prefs, Prefab(
        data.name,
        function()
            local inst = CreateEntity()

            inst.entity:AddTransform()
            inst.entity:AddNetwork()

            inst:AddTag("FX")

            if data.fn_common ~= nil then
                data.fn_common(inst)
            end

            inst.entity:SetPristine()
            if not TheWorld.ismastersim then
                inst.OnEntityReplicated = OnEntityReplicated
                return inst
            end

            inst.persists = false
            inst.AttachToOwner = AttachToOwner

            if data.fn_server ~= nil then
                data.fn_server(inst)
            end

            return inst
        end,
        data.assets,
        nil
    ))
end

---------------
---------------

MakeFx({ -- 锦上添花buff：飞溅晗猪草花瓣
    name = "buff_pl_piggycorolla_fx",
    assets = {
        Asset("ANIM", "anim/lavaarena_heal_projectile.zip"), -- 官方的熔炉奶杖击中特效动画
        Asset("ANIM", "anim/buff_pl_piggycorolla_fx.zip")
    },
    fn_common = nil,
    fn_anim = function(inst)
        inst.AnimState:SetBank("lavaarena_heal_projectile")
        inst.AnimState:SetBuild("buff_pl_piggycorolla_fx")
        inst.AnimState:PlayAnimation("hit")
        inst.AnimState:SetScale(1.2, 1.2)
        inst.AnimState:SetFinalOffset(3)
        inst.AnimState:SetLightOverride(0.6)
    end,
    fn_remove = nil
})

---------------
---------------

return unpack(prefs)
